#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <iostream>
#include <ctime>
using namespace std;
#define MAXNODE 10000

typedef string KEYTYPE;


typedef struct _TUserInfo {
	KEYTYPE id;
	void* param;
	int cnt;
	bool visited;
	struct _TUserInfo* father;
	struct _TUserInfo* left;
	struct _TUserInfo* right;
} TUserInfo;

TUserInfo nodePool[MAXNODE+100];
int emptylist[MAXNODE+100];
int emptyIdx = 0;

TUserInfo* tUserInfo(KEYTYPE id) {
	TUserInfo* info;// = (TUserInfo*)malloc(sizeof(TUserInfo));
	info = &nodePool[emptylist[emptyIdx++]];
	info->id = id;
	info->father = NULL;
	info->left = NULL;
	info->right = NULL;
	info->param = NULL;
	info->visited = false;
	info->cnt = 1;
	return info;
}

bool isLeft(TUserInfo* fa, TUserInfo* node) {
	return (fa->left!=NULL && fa->left->id == node->id);
}
bool isRight(TUserInfo* fa, TUserInfo* node) {
	return (fa->right!=NULL && fa->right->id == node->id);
}
void deleteNode(TUserInfo* node) {
	--emptyIdx;
	emptylist[emptyIdx] = (node-nodePool);
	//free(node);
}

void zig(TUserInfo* root) {
	root->father->left = root->right;
	if (root->right != NULL) root->right->father = root->father;

	TUserInfo* fafa = root->father->father;
	if (fafa != NULL) {
		if (isLeft(fafa, root->father))
			fafa->left = root;
		else
			fafa->right = root;
	}
	root->father->father = root;

	root->right = root->father;
	root->father = fafa;
}

void zag(TUserInfo* root) {
	root->father->right = root->left;
	if (root->left != NULL) root->left->father = root->father;

	TUserInfo* fafa = root->father->father;
	if (fafa != NULL) {
		if (isRight(fafa, root->father))
			fafa->right = root;
		else
			fafa->left = root;
	}
	root->father->father = root;

	root->left = root->father;
	root->father = fafa;
}

void splay(TUserInfo* root, TUserInfo** rootUser) {
	while (true) {
		if (root->father == NULL)
			break;
		TUserInfo* fafa = root->father->father;

		if (fafa == NULL) {
			if (isLeft(root->father, root))
				zig(root);
			else
				zag(root);
			continue;
		}

		if (isLeft(fafa, root->father)) {
			if (isLeft(root->father, root)) {
				zig(root->father);
				zig(root);
			}
			else {
				zag(root);
				zig(root);
			}
		}
		else {
			if (isRight(root->father, root)) {
				zag(root->father);
				zag(root);
			}
			else {
				zig(root);
				zag(root);
			}
		}
	}
	*rootUser = root;
}

bool addUser(TUserInfo* root, KEYTYPE id, TUserInfo** rootUser) {
	if (*rootUser == NULL) {
		*rootUser = tUserInfo(id);
		return true;
	}
	TUserInfo* newUser = tUserInfo(id);
	while (true) {
		if (id == root->id) {
			++root->cnt;
			deleteNode(newUser);
			return false;
		}
		if (id < root->id) {
			if (root->left == NULL) {
				root->left = newUser;
				break;
			}
			else
				root = root->left;
		}
		else {
			if (root->right == NULL) {
				root->right = newUser;
				break;
			}
			else
				root = root->right;
		}
	}
	newUser->father = root;

	if (rand()%10==0)
		splay(newUser, rootUser);
	return true;
}

void deleteSingleSubtreeNode(TUserInfo* root, TUserInfo** rootUser) {
	if (root->left == NULL) {
		if (root->father == NULL)
			*rootUser = root->right;
		else {
			if (isLeft(root->father, root))
				root->father->left = root->right;
			else
				root->father->right = root->left;
		}
		if (root->right != NULL)
			root->right->father = root->father;
		deleteNode(root);
	}
	else if (root->right == NULL) {
		if (root->father == NULL)
			*rootUser = root->left;
		else {
			if (isRight(root->father, root))
				root->father->right = root->left;
			else
				root->father->left = root->right;
		}
		if (root->left != NULL)
			root->left->father = root->father;
		deleteNode(root);
	}
}

bool deleteUser(TUserInfo* root, KEYTYPE id, TUserInfo** rootUser) {
	while (true) {
		if (root == NULL) return false;
		if (root->id == id) {
			if (root->left==NULL || root->right == NULL) {
				TUserInfo* fa = root->father;
				deleteSingleSubtreeNode(root, rootUser);
				if (fa != NULL)
					splay(fa, rootUser);
				break;
			}
			TUserInfo* theMaxNode = root->left;
			while (theMaxNode->right != NULL) theMaxNode = theMaxNode->right;
			root->id = theMaxNode->id;
			deleteSingleSubtreeNode(theMaxNode, rootUser);
			splay(root, rootUser);
			break;
		}
		if (id < root->id) root = root->left;
		else root = root->right;
	}
	return true;
}

bool find(TUserInfo* root, KEYTYPE id) {
	while (true) {
		if (root == NULL) return false;
		if (root->id == id) return true;
		if (id < root->id) root = root->left;
		else root = root->right;
	}
}



TUserInfo* rootUser = NULL;
int total = 0;
void travel(TUserInfo* root) {
	while (true) {
		if (root == NULL) break;
		if (root->left != NULL && !root->left->visited) {
			root = root->left;
			continue;
		}
		if (!root->visited) {
			printf("%s %.4lf\n", root->id.c_str(), root->cnt * 100.0 / total);
			root->visited = true;
		}
		if (root->right != NULL && !root->right->visited) {
			root = root->right;
			continue;
		}
		TUserInfo* fa = root->father;
		deleteSingleSubtreeNode(root, &rootUser);
		root = fa;
	}
}

char buf[100];

int main(void)
{
	srand(time(0));
	for (int i=0; i<MAXNODE+100; ++i)
		emptylist[i] = i;
	int totCase;
	scanf("%d\n", &totCase);
	for (int testcase = 0; testcase < totCase; ++testcase) {
		for (int i=0; i<1000001; ++i) {
			buf[0] = 0;
			gets(buf);
			if (strlen(buf) == 0 || buf[0] == 0) break;
			++total;
			addUser(rootUser, buf, &rootUser);
		}
		if (testcase>0) printf("\n");
		travel(rootUser);
		total = 0;
	}
	return 0;
}
